describe('Storage enumerate', () => {
  ["localStorage", "sessionStorage"].forEach(function(name) {
    test(function() {
      assert_true(name in window, name + " exist");

      var storage = window[name];
      storage.clear();

      Storage.prototype.prototypeTestKey = "prototypeTestValue";
      storage.foo = "bar";
      storage.fu = "baz";
      storage.batman = "bin suparman";
      storage.bar = "foo";
      storage.alpha = "beta";
      storage.zeta = "gamma";

      const enumeratedArray = Object.keys(storage);
      enumeratedArray.sort();  // Storage order is implementation-defined.

      const expectArray = ["alpha", "bar", "batman", "foo", "fu", "zeta"];
      expect(enumeratedArray).toEqual(expectArray);

      // 'prototypeTestKey' is not an actual storage key, it is just a
      // property set on Storage's prototype object.
      assert_equals(storage.length, 6);
      assert_equals(storage.getItem("prototypeTestKey"), null);
      assert_equals(storage.prototypeTestKey, "prototypeTestValue");
    }, name + ": enumerate a Storage object and get only the keys as a result and the built-in properties of the Storage object should be ignored");

    test(function() {
      const storage = window[name];
      storage.clear();

      storage.setItem("foo", "bar");
      storage.baz = "quux";
      storage.setItem(0, "alpha");
      storage[42] = "beta";

      for (let prop in storage) {
        if (!storage.hasOwnProperty(prop))
          continue;
        const desc = Object.getOwnPropertyDescriptor(storage, prop);
        assert_true(desc!.configurable);
        assert_true(desc!.enumerable);
        assert_true(desc!.writable);
      }

      const keys = Object.keys(storage);
      keys.sort();  // Storage order is implementation-defined.
      expect(keys).toEqual(["0", "42", "baz", "foo"]);

      const values = Object.values(storage);
      values.sort();  // Storage order is implementation-defined.
      expect(values).toEqual(["alpha", "bar", "beta", "quux"]);
    }, name + ": test enumeration of numeric and non-numeric keys");
  });
});